# encoding: utf-8
from pyo import *


class Grain:
    def __init__(self, type='ScribbingLooper'):
        
        self.type = type
        
        self.table = SndTable(SNDS_PATH+"/transparent.aif")
        self.sndDur = self.table.getDur()
        
        self.env = HannTable()
        
        
        
        self.scrib = SigTo(0.5, time=0.1, init=0.5, mul=self.table.getSize(), 
                           add=Noise(5))

        self.grnX = SigTo(value=0.5, time=0.05, init=0.5)
        self.grnY = SigTo(value=0.5, time=0.05, init=0.5)
        self.grnZ = Sig(0.001)

        self.loopWindow = self.grnZ*4.
                           
        self.scribLoop = Phasor(self.table.getRate(), 
                                mul=self.table.getSize()*self.loopWindow,
                                add=self.table.getSize()*self.grnX)
                           
        self.phazPos = Phasor(freq=self.table.getRate()*self.grnX, phase=0, 
                              mul=self.table.getSize(), add=Noise(10))


        
        self.dur = Noise(mul=Clip(self.grnZ, min=0, max=0.025), add=.1) 
        
        self.grn = Granulator( table=self.table,    
                            env=self.env,        
                            pitch=self.grnY,      
                            pos=self.scrib,        
                            dur=self.dur,        
                            grains=40,      
                            basedur=.1,      
                            mul=.1).stop()
                            
        self.type_dict = {'Scribbing': self.scrib,'ScribbingLooper': self.scribLoop,
                          'PhasorTableRead': self.phazPos}
                        
          
                         
    def changeTable(self, snd):
        self.table.sound = snd
        
    def changeType(self, type):
        self.grn.pos = self.type_dict[type]
        self.type = type
    
    def changeX(self, x):
        self.scrib.value = x
        self.grnX.value = x

    def changeY(self, y):
        self.grnY.value = y
        
    def grainDur(self, z):
        self.grnZ.value = z

    def sig(self):
        return self.grn
        

class FxSwitch:
    def __init__(self,input,fx='BandSplitDelay'):
        self.fx = fx
        self.input = input
        
        self.fxX = SigTo(value=0.5, time=0.2, init=0.5)
        self.fxY = SigTo(value=0.5, time=0.05, init=0.5)
        self.fxZ = SigTo(value=0.5, time=0.05, init=0.5)
        
        self.num= 6
       
        self.bandSplit = BandSplit(self.input,num=self.num,min=40,max=18000,q=1,mul=.75,add=0)
        
        self.dls= [i* .0025 for i in range(1,self.num+1) if (i%2) == 1]
        
        self.bandSplitDelay = Delay(self.bandSplit,maxdelay=5,delay=self.dls*self.fxX,
                                    feedback=self.fxY,mul=.5).stop()
        
        
        
        self.verb = Freeverb(self.bandSplitDelay,size=.995,damp=.15,bal=.15,mul=.5).out()
        
        self.delay = Delay(self.input.out(), maxdelay=10, delay=self.fxX*4, 
                           feedback=self.fxY).stop()
                           
        self.disto = Disto(self.input, drive=self.fxX, slope=self.fxY, 
                           mul=.5).stop()
                           
        self.degrade = Degrade(self.input, bitdepth=Sig(self.fxX,mul=20,add=2),
                               srscale=Sig(self.fxY,mul=1,add=.01),mul=1.5).stop()
                               
        self.reverb = WGVerb(self.input.out(), feedback=self.fxX, bal=self.fxZ, 
                               mul=1.).stop()
                             
        self.harmo = Harmonizer(self.input.out(), 
                                transpo=Sig(self.fxX,mul=24,add=-12),
                                feedback=self.fxY).stop()
                                
        self.fx_dict = {'Reverb': self.reverb, 'Disto': self.disto, 
                        'Degrade': self.degrade, 'Delay': self.delay, 
                        'BandSplitDelay':self.bandSplitDelay,
                        'Harmonizer': self.harmo}
        self.fx_dict[fx].out()
        
    def changeFx(self, fx):
        self.fx_dict[self.fx].stop()
        self.fx_dict[fx].out()
        self.fx = fx
        
    def changeX(self, x):
        self.fxX.value = x

    def changeY(self, y):
        self.fxY.value = y
        
 
